﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ILRuntime.Runtime.Enviorment;
using Mono.Data.Sqlite;
using System.Linq;

//用于管理全局数据资源
public class ResourceManager : MonoBehaviour {

    public string ScriptFileName = "ScriptDll";//脚本文件名
    public string CardDBFileName = "Card";//卡片数据库文件名
    public uint RandomSeed = 1000;

    DataManager BasicData;//卡片/特性数据列表
    //ScriptManager ScriptOp;//脚本管理

    private string ScriptPath;//脚本路径
    private string DBPath;//数据库路径

	// Use this for initialization
	void Start () {

        //ScriptPath = Application.streamingAssetsPath + "/" + ScriptFileName;
        DBPath= "data source=" + Application.streamingAssetsPath + "/" + CardDBFileName+".db";

        //StartCoroutine(LoadScriptAssembly());
        StartCoroutine(LoadCardAssembly(Application.streamingAssetsPath + "/TestGroup.mdk"));
    }

	// Update is called once per frame
	void Update () {
		
	}
    /*
    //脚本文件加载
    IEnumerator LoadScriptAssembly()
    {
        //加载DLL文件
#if UNITY_ANDROID
        WWW www = new WWW(Application.streamingAssetsPath + "/" + ScriptFileName+".dll");
#else
        WWW www = new WWW("file:///" + ScriptPath + ".dll");
#endif
        while (!www.isDone)//如果资源未加载完
            yield return null;
        if (!string.IsNullOrEmpty(www.error))
            Debug.LogError(www.error);
        byte[] dll = www.bytes;
        www.Dispose();
        //加载PDB文件
#if UNITY_ANDROID
        www = new WWW(Application.streamingAssetsPath + "/" + ScriptFileName+".pdb");
#else
        www = new WWW("file:///" + ScriptPath + ".pdb");
#endif
        while (!www.isDone)
            yield return null;

        if (!string.IsNullOrEmpty(www.error))
            Debug.LogError(www.error);
        byte[] pdb = www.bytes;
        ScriptOp = new ScriptManager(ScriptFileName, dll, pdb);
    }    */
    //卡组数据加载
    IEnumerator LoadCardAssembly(string path)
    {
        WWW www = new WWW(path);
        while (!www.isDone)//如果资源未加载完
            yield return null;
        if (!string.IsNullOrEmpty(www.error))
            Debug.LogError(www.error);
        string temp = System.Text.Encoding.UTF8.GetString(www.bytes);
        BasicData = new DataManager(DBPath,temp,null);
        Debug.Log("CardGroupLoadSuccess!");
    }
}

/// <summary>
/// 数据库交互管理器
/// </summary>
public class SQLiteManager
{
    private int count;//卡片计数，用于GID
    private string dbPath;//数据库路径
    private string sqlcommand;//查询指令
    private SqliteConnection dbConnection;//数据库连接
    private SqliteCommand dbCommand;//数据库指令格式
    private SqliteDataReader dataReader;//结果集
    /// <summary>
    /// 初始化数据库连接
    /// </summary>
    /// <param name="Path"></param>
    public SQLiteManager(string Path)
    {
        count = 0;
        dbPath = Path;
        try
        {
            //构造数据库连接
            dbConnection = new SqliteConnection(dbPath);
            //打开数据库
            dbConnection.Open();
            Debug.Log("SqlConnectSuccess!");
        }
        catch (System.Exception e)
        {
            Debug.Log(e.Message);
        }
    }
    /// <summary>
    /// 读取指定的卡片组
    /// </summary>
    /// <param name="cardName">卡片名数组</param>
    /// <param name="own">卡片所有者</param>
    /// <param name="effects">数据库的特性列表</param>
    /// <returns>返回读取完毕的卡片组</returns>
    public Card[] LoadCardGroup(string[] cardName,Owner own,TEffect[] effects)
    {
        int time = 0;//卡片组计数
        CardType cardTypet;//临时保存卡牌类型
        Card[] temp = new Card[cardName.Length-2];//卡片组数组
        SqliteDataReader tempdata;//临时保存查询结果1
		bool IsCharacter=false;//读取卡组中是否为角色卡读取
		string[] cardMark;//卡片名分割后的字符结果
        string id = null;//临时存储卡片数据库的ID
        List<int> Teffect = null;//单卡特性表索引序列
        //循环卡名列表
        foreach (string s in cardName)
        {
            //如果是角色卡区域 切换为角色卡读取方式，之后再读取到#切换为其他卡读取方式
            if (s[0] == '#'){
				IsCharacter=(!IsCharacter);
				continue;
			}
            //分割当前卡名为系列+编号
            cardMark = s.Split('-');
			//如果是角色卡
            if(IsCharacter){
				//t[0]就是系列；t[2]就是编号
				//下面开始查询              
                sqlcommand = "select b.*,c.* from Basic b,Character c where b.Series=" +
                    "(select id from Series where Call='" + cardMark[0] + "') and b.Num=" + cardMark[2] + " and b.ID=c.ID";
                ExecuteQuery();
                //卡本身数据结果集
                tempdata = dataReader;                
                while (tempdata.Read())
                {//获取卡牌ID
                    int t = 0;
                    id = dataReader["ID"].ToString();
                    //读取技能组
                    sqlcommand = "select * from Skill where ID=" + id;
                    ExecuteQuery();
                    List<Skill> tskills = new List<Skill>();
                    while (dataReader.Read())
                    {
                        int.TryParse(dataReader["SkillType"].ToString(), out t);
                        tskills.Add(new Skill(
                            (SkillType)t,
                            dataReader["SkillText"].ToString())
                            );
                    }
                    //角色技能组
                    Skill[] skills = tskills.ToArray();
                    //角色卡数据准备
                    int.TryParse(tempdata["Num"].ToString(), out t);
                    int cardTypet1 = (int)tempdata["CardType"];
                    cardTypet = (CardType)(int.Parse(tempdata["CardType"].ToString()));
                    //卡片装载
                    temp[time] = new CharacterCard(
                        count,//gid
                        own,//控制权
                        cardMark[0],//系列
                        t,//编号
                        tempdata["Rare"].ToString(),//稀有度
                        tempdata["Name"].ToString(),//卡名
                        bool.Parse(tempdata["IsfinalCard"].ToString().ToLower()),//终符标记
                        cardTypet,//卡片类型
                        tempdata["Illust"].ToString(),//绘师信息

                        tempdata["Title"].ToString(),//角色称号信息
                        tempdata["Describe"].ToString(),//角色介绍信息
                        skills//技能组
                        );
                    time++;
                    count++;
                }
            }
			else{
				//t[0]是系列；t[1]就是编号
				//下面开始查询
                sqlcommand= "select * from Basic where Series=" +
                    "(select id from Series where Call='" + cardMark[0] + "') and Num=" + cardMark[1] + " and CardType!=1";
                ExecuteQuery();
                tempdata = dataReader;
                while (tempdata.Read())
                {
                    int t = 0;
                    int.TryParse(tempdata["Num"].ToString(), out t);
                    //获取卡牌ID
                    id = tempdata["ID"].ToString();
                    //获取卡牌类别
                    cardTypet = (CardType)(int.Parse(tempdata["CardType"].ToString()));
                    //根据卡片类型查询对应卡结果
                    switch (cardTypet)
                    {
                        case CardType.Battle:
                            {
                                //查询作为战斗卡的战斗卡信息
                                //先找对应的特性映射表
                                sqlcommand = "select * from [Connect_B&T] where BID=" + id;
                                ExecuteQuery();
                                SqliteDataReader Tdata = dataReader;
                                while (Tdata.Read())
                                {
                                    //根据映射表中的映射的特性ID读取对应的特性
                                    sqlcommand = "select * from TList where ID=" + Tdata["TID"];
                                    ExecuteQuery();
                                    Teffect = new List<int>();
                                    //跟已经读取的内部特性表匹配，保存对应ID
                                    while (dataReader.Read())
                                    {
                                        string tt = dataReader["TName"].ToString();
                                        int EffectIndex = -1;
                                        foreach (TEffect te in effects)
                                        {
                                            if (tt.Equals(te.TName, System.StringComparison.OrdinalIgnoreCase))
                                            {
                                                EffectIndex = te.GID;
                                                break;
                                            }
                                        }
                                        Teffect.Add(EffectIndex);
                                    }
                                }
                                //然后找对应的战斗卡信息
                                sqlcommand = "select * from Battle where ID=" + id;
                                ExecuteQuery();
                                //装载卡片
                                while (dataReader.Read())
                                {
                                    try
                                    {
                                        temp[time] = new BattleCard(
                                            count,//gid
                                            own,//控制权
                                            cardMark[0],//系列
                                            t,//编号
                                            tempdata["Rare"].ToString(),//稀有度
                                            tempdata["Name"].ToString(),//卡名
                                            bool.Parse(tempdata["IsfinalCard"].ToString().ToLower()),//终符标记
                                            cardTypet,//卡片类型
                                            tempdata["Illust"].ToString(),//绘师信息

                                            int.Parse(dataReader["Level"].ToString()),//华丽度
                                            int.Parse(dataReader["Cost"].ToString()),//代价
                                            int.Parse(dataReader["BattleNum"].ToString()),//战斗力数值
                                            (BattleType)(int.Parse(dataReader["BattleType"].ToString())),//战斗类型
                                            dataReader["EffectText"].ToString(),//效果描述
                                            dataReader["ConditionText"].ToString(),//效果条件
                                            Teffect//对应特性表
                                            );
                                        time++;
                                        count++;
                                    }catch(System.Exception e)
                                    {
                                        Debug.Log(e);
                                    }
                                }
                            }
                            break;
                        case CardType.Special:
                            {
                                //查询作为特殊卡的特殊卡信息
                                sqlcommand= "select * from Special where ID=" + id;
                                ExecuteQuery();
                                //装载卡片
                                while (dataReader.Read())
                                {
                                    try
                                    {
                                        temp[time] = new SpecialCard(
                                            count,//gid
                                            own,//控制权
                                            cardMark[0],//系列
                                            t,//编号
                                            tempdata["Rare"].ToString(),//稀有度
                                            tempdata["Name"].ToString(),//卡名
                                            bool.Parse(tempdata["IsfinalCard"].ToString().ToLower()),//终符标记
                                            cardTypet,//卡片类型
                                            tempdata["Illust"].ToString(),//绘师信息

                                            int.Parse(dataReader["Level"].ToString()),//华丽度
                                            int.Parse(dataReader["Cost"].ToString()),//代价
                                            dataReader["EffectText"].ToString(),//效果描述
                                            dataReader["ConditionText"].ToString(),//效果条件
                                            (SpecialType)(int.Parse(dataReader["CardType"].ToString()))//特殊卡类型
                                            );
                                        time++;
                                        count++;
                                    }catch(System.Exception e)
                                    {
                                        Debug.Log(e);
                                    }
                                }
                            }
                            break;
                        default:
                            break;
                    }
                }
               

            }
        }
        return temp;
    }
    /// <summary>
    /// 读取存在的特性表
    /// </summary>
    /// <returns>返回数据库中已有的所有特性列表</returns>
    public TEffect[] LoadTGroup()
    {
        List<TEffect> tempT = new List<TEffect>();
        sqlcommand = "select * from TList";
        ExecuteQuery();
        int t = 0;
        while (dataReader.Read())
        {
            tempT.Add(new TEffect(
                t,
                dataReader["TName"].ToString(),
                dataReader["TText"].ToString()
                ));
            t++;
        }
        TEffect[] temp = tempT.ToArray();
        return temp;
    }

    /// <summary>
    /// 执行SQL命令
    /// </summary>
    /// <returns>The query.</returns>
    /// <param name="queryString">SQL命令字符串</param>
    private void ExecuteQuery()
    {
        dbCommand = dbConnection.CreateCommand();
        dbCommand.CommandText = sqlcommand;
        dataReader = dbCommand.ExecuteReader();
    }

    /// <summary>
    /// 关闭数据库连接
    /// </summary>
    public void CloseConnection()
    {
        //销毁Command
        if (dbCommand != null)
        {
            dbCommand.Cancel();
        }
        dbCommand = null;

        //销毁Reader
        if (dataReader != null)
        {
            dataReader.Close();
        }
        dataReader = null;

        //销毁Connection
        if (dbConnection != null)
        {
            dbConnection.Close();
        }
        dbConnection = null;
    }
}

/// <summary>
/// 卡片/特性数据管理器
/// 用于存放全局数据，作为内存数据库使用
/// </summary>
public class DataManager
{
    private Card[] Player1Group { get; set; }//玩家1[主机]卡组
    private Card[] Player2Group { get; set; }//玩家2[客机]卡组
    private Card[] PublicGroup { get; set; }//共有卡组
    private Card[] UnknownGroup { get; set; }//未知卡组
    private TEffect[] Tlist { get; }//特性组
    private SQLiteManager SQL;//与数据库交互
    /// <summary>
    /// 初始化数据管理器
    /// </summary>
    /// <param name="path">数据库文件路径</param>
    public DataManager(string path)
    {
        SQL = new SQLiteManager(path);
        Tlist=SQL.LoadTGroup();//立即初始化现有的所有特性列表
    }
    /// <summary>
    /// 初始化数据管理器[包括双方卡组]
    /// </summary>
    /// <param name="path">数据库文件路径</param>
    /// <param name="player1G">玩家1[主机]卡片组字符串</param>
    /// <param name="player2G">玩家2[客机]卡片组字符串</param>
    public DataManager(string path, string player1G, string player2G)
    {
        SQL = new SQLiteManager(path);
        Tlist = SQL.LoadTGroup();//立即初始化现有的所有特性列表
        SetCardGroup(player1G,player2G);
    }
    /// <summary>
    /// 设置卡片组数据
    /// </summary>
    /// <param name="player1G">玩家1[主机]卡片组字符串</param>
    /// <param name="player2G">玩家2[客机]卡片组字符串</param>
    private void SetCardGroup(string player1G,string player2G)
    {
        if(player1G != null)
            Player1Group = GetCardGroup(player1G,Owner.Player1);
        if(player2G != null)
            Player2Group = GetCardGroup(player2G, Owner.Player2);
    }
    /// <summary>
    /// 添加新卡片[战斗过程中]
    /// </summary>
    /// <param name="cardName">卡片名组</param>
    /// <param name="o">卡片所有者</param>
    /// <returns>添加成功True</returns>
    public bool AddNewCard(string[] cardName,Owner o)
    {
        Card[] temp=SQL.LoadCardGroup(cardName, o, Tlist);
        if (temp.Length == 0)//说明对应卡片未能找到
            return false;
        switch (o)
        {
            case Owner.Player1:
                Player1Group.Concat(temp).ToArray();
                return true;
            case Owner.Player2:
                Player2Group.Concat(temp).ToArray();
                return true;
            case Owner.Public:
                PublicGroup.Concat(temp).ToArray();
                return true;
            case Owner.Unknown:
                UnknownGroup.Concat(temp).ToArray();
                return true;
            default:
                return false;

        }
    }
    /// <summary>
    /// 根据字符串和所有者设置卡组
    /// </summary>
    /// <param name="g">卡组字符串</param>
    /// <param name="own">卡组所有者</param>
    /// <returns>获取到的卡组列表</returns>
    private Card[] GetCardGroup(string g,Owner own)
    {
        string[] temp = null;
        //分割卡组文件字符串[当前规则为：一行显示一张卡名，详情浏览.mdk文件]
        temp = g.Split(new string[] { "\r\n" }, System.StringSplitOptions.None);
        return SQL.LoadCardGroup(temp,own,Tlist);
    }

}

/// <summary>
/// 脚本管理器
/// </summary>
public class ScriptManager
{
    private AppDomain appdomain;//脚本文件
    private string ScriptName;//脚本文件名

    /// <summary>
    /// 初始化脚本文件资源[调试]
    /// </summary>
    /// <param name="name">脚本文件名</param>
    /// <param name="dll">dll字节流</param>
    /// <param name="pdb">pdb字节流</param>
    public ScriptManager(string name,byte[]dll,byte[] pdb)
    {
        ScriptName = name;
        appdomain = new AppDomain();
        using (System.IO.MemoryStream fs = new System.IO.MemoryStream(dll))
        {
            using (System.IO.MemoryStream p = new System.IO.MemoryStream(pdb))
            {
                appdomain.LoadAssembly(fs, p, new Mono.Cecil.Pdb.PdbReaderProvider());
            }
        }
        InitializeILRuntime();
        OnScriptLoaded();
    }
    /// <summary>
    /// 初始化脚本文件资源
    /// </summary>
    /// <param name="name">脚本文件名</param>
    /// <param name="dll">dll字节流</param>
    public ScriptManager(string name, byte[] dll)
    {
        ScriptName = name;
        appdomain = new AppDomain();
        using (System.IO.MemoryStream fs = new System.IO.MemoryStream(dll))
        {
            appdomain.LoadAssembly(fs);
        }
        InitializeILRuntime();
        OnScriptLoaded();
    }
    /// <summary>
    /// DLL脚本注册相关
    /// </summary>
    private void InitializeILRuntime()
    {

    }
    /// <summary>
    /// DLL脚本加载完毕处理
    /// </summary>
    private void OnScriptLoaded()
    {
        //确认加载正常
        appdomain.Invoke(ScriptName + ".main", "LoadTest", null, null);
    }

    /// <summary>
    /// 执行脚本中对应类的函数
    /// </summary>
    /// <param name="classname">类名</param>
    /// <param name="funname">函数名</param>
    /// <param name="p">参数组</param>
    public void RunScriptFun(string classname,string funname,params object[] p)
    {
        appdomain.Invoke(ScriptName+"."+classname,funname,p);
    }
}